'use client';
import React, { useState, useEffect } from "react";
import { InitAPI, Common, defaultConfig } from "cess-js-sdk-frontend";
import { sleep } from "./utils/common";
import * as formatter from "./utils/formatter";
import * as antdHelper from "./utils/antd-helper";
import request from "./utils/request";

import moment from "moment";

import { Spin } from "antd";

import QrSvg from '@wojtekmaj/react-qr-svg';
import copy from "copy-to-clipboard";
import webconfig from './webconfig';
//for evm
import { getMappingAccount, signAndSendEvm } from 'evm-account-mapping-sdk'
import { custom, createWalletClient } from 'viem'
import { mainnet } from 'viem/chains'



let unsubBalance = '';
let sdk = null;
let inputValue = {
	staking: { amount: 0, address: '' },
	send: { amount: 0, address: '' },
	nominate: { amount: 0, address: '' },
}
let walletClient;
let mappingAccount;
let pageIndex = 1;
let historyCount = 0;
let historyTotalPage = 0;

export function Main() {
	const [loading, setLoading] = useState(null);
	const [connectStatus, setConnectStatus] = useState('--');
	const [current, setCurrent] = useState("login");
	const [boxTitle, setBoxTitle] = useState("Receive");
	const [accountType, setAccountType] = useState("polkdot");
	const [showAddressType, setShowAddressType] = useState("CESS");
	const [historys, setHhistorys] = useState();
	const [accout, setAccout] = useState({});
	const [balance, setBalance] = useState(0);
	const [available, setAvailable] = useState(0);
	const [staking, setStaking] = useState(0);
	const [nominate, setNominate] = useState(0);


	const onClick = e => {
		setCurrent(e);
		setBoxTitle(e);
	};
	useEffect(() => {
		init();
		return () => {
			if (unsubBalance) {
				unsubBalance();
			}
		}
	}, []);
	const init = async () => {
		setConnectStatus('connecting...');
		try {
			const { api, keyring } = await InitAPI(defaultConfig);
			window.api = api;
			window.keyring = keyring;
			setConnectStatus('connect success');
			console.log("rpc connect success");
			return { api, keyring };
		} catch (e) {
			setConnectStatus(e.message);
			console.log('has error');
			console.log(e);
		}
	};
	const connectPolkdotWallet = async () => {
		setLoading('login-polkdot');
		while (!window.api || !window.keyring) {
			await sleep(500);
		}
		setConnectStatus('opening wallet');
		sdk = new Common(window.api, window.keyring);
		let accounts = await sdk.getAccountsFromWallet();
		console.log(accounts);
		if (accounts.length > 0) {
			setConnectStatus('login success');
			setAccout(accounts[0]);
			setCurrent('dashboard');
			setAccountType('polkdot');
			subBalance(accounts[0].address);
			pageIndex = 1;
			loadHistoryList(accounts[0].address);
		}
		setLoading(null);
		return accounts;
	};
	const connectEvmWallet = async () => {
		setLoading('login-evm');
		while (!window.api || !window.keyring) {
			await sleep(500);
		}
		setConnectStatus('opening wallet');
		walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum) })
		const [address] = await walletClient.requestAddresses();
		console.log({ address })
		const SS58Prefix = (window.api?.consts?.system?.ss58Prefix || 11330).toNumber();
		let ma = await getMappingAccount(window.api, walletClient, { address }, { SS58Prefix });
		mappingAccount = ma;
		let acc = ma;
		acc.address = ma.substrateAddress;
		setAccout(acc);
		setConnectStatus('login success');
		setAccountType('evm');
		setLoading(null);
		setCurrent('dashboard');
		subBalance(acc.address);
		pageIndex = 1;
		loadHistoryList(acc.address);
	}
	const subBalance = async (address) => {
		console.log('start sub banlace.')
		if (unsubBalance) {
			unsubBalance();
		}
		unsubBalance = await api.query.system.account(address, ({ nonce, data: balance }) => {
			console.log({ balance });
			let availableB = formatter.fixed(balance.free / 1e18);
			setAvailable(availableB);
			let stakingB = formatter.fixed(balance.reserved / 1e18);
			setStaking(stakingB);
			let nominateB = 0;//formatter.fixed(balance.frozen / 1e18);
			setNominate(nominateB);
			let all = availableB + stakingB + nominateB;
			console.log('banlace:', all);
			setBalance(all);
			loadHistoryList(address);
		});
		return unsubBalance;
	}

	const onCopy = (txt) => {
		console.log('copy ', txt);
		copy(txt);
		antdHelper.notiOK('Copy success.');
	}
	const onLogout = () => {
		if (unsubBalance) {
			unsubBalance();
		}
		antdHelper.notiOK('Logout success.');
		setAccout({});
		setCurrent('login');
	}
	const subState = (d) => {
		console.log(d);
		if (typeof d == 'string') {
			antdHelper.noti(d);
		}
		// else {
		// 	antdHelper.noti(d.status.toString());
		// }
	}
	const onStaking = () => {
		let { address, amount } = formatParams(inputValue.staking);
		let extrinsic = window.api.tx.sminer.increaseCollateral(address, amount);
		submitTx(extrinsic);
	}
	const onSend = () => {
		let { address, amount } = formatParams(inputValue.send);
		let extrinsic = window.api.tx.balances.transfer(address, amount);
		submitTx(extrinsic);
	}
	const onNominate = async () => {
		let { address, amount } = formatParams(inputValue.nominate);
		let extrinsic = window.api.tx.staking.nominate([address]);
		let ret = await submitTx(extrinsic, true);
		if (ret.msg == 'ok') {
			extrinsic = window.api.tx.staking.bond(amount, 'Staked');
			submitTx(extrinsic);
		}
	}
	const onInput = (e, k1, k2) => {
		console.log('oninput', e, k1, k2);
		inputValue[k1][k2] = e.target.value;
	}
	const loadHistoryList = async (addr) => {
		let address = addr || accout.address;
		// address = "cXffK7BmstE5rXcK8pxKLufkffp9iASMntxUm6ctpR6xS3icV";
		let url = `/transfer/query?Acc=${address}&pageindex=${pageIndex}&pagesize=${webconfig.historyPageSize}`;
		let ret = await request(url);
		console.log(ret);
		if (ret.msg != 'ok') {
			return antdHelper.notiError(ret.msg);
		}
		if (!ret.data.content) {
			return antdHelper.notiError('API error');
		}
		let list = ret.data.content.map(t => {
			return {
				key: t.hash,
				amount: formatter.formatBalance(t.amount),
				type: t.from == address ? 'Send' : 'Receive',
				from: formatter.formatAddress(t.from),
				to: formatter.formatAddress(t.to),
				time: moment(t.timestamp).format('YYYY/MM/DD HH:mm:ss')
			}
		});
		historyCount = ret.data.count;
		historyTotalPage = parseInt(historyCount / webconfig.historyPageSize);
		if (historyCount % webconfig.historyPageSize != 0) {
			historyTotalPage++;
		}
		setHhistorys(list);
	}
	const onNextHistoryPage = (l) => {
		pageIndex = pageIndex + l;
		loadHistoryList();
	}
	const formatParams = (obj) => {
		console.log(obj);
		if (!obj.amount) {
			antdHelper.alertError('Amount is required.');
			return null;
		}
		let amount = parseInt(obj.amount);
		if (amount < 1) {
			antdHelper.alertError('Amount error.');
			return null;
		}
		amount = BigInt(amount) * BigInt(1e18);
		// amount = amount * 1e18;
		if (!obj.address) {
			antdHelper.alertError('Account address is required.');
			return null;
		}
		return { address: obj.address, amount };
	}
	const submitTx = async (extrinsic, hideSuccessTips) => {
		let ret = '';
		try {
			setLoading('signature');
			if (accountType == 'polkdot') {
				ret = await sdk.signAndSend(accout.address, extrinsic, subState);
			} else {
				const result = await signAndSendEvm(
					extrinsic,
					window.api,
					walletClient,
					mappingAccount
				);
				const trId = result.status.asInBlock.toHex();
				ret = { msg: 'ok', data: trId };
			}
			if (ret.msg == 'ok') {
				if (!hideSuccessTips) {
					antdHelper.alertOk('Transfer success.')
				}
			} else {
				antdHelper.alertError(ret.msg);
			}
		} catch (e) {
			console.log(e);
			if (e.message) {
				antdHelper.alertError(e.message);
			} else {
				antdHelper.noti(e);
			}
		} finally {
			setLoading(null);
		}
		return ret;
	}

	return (
		<div className="App">
			<a className="header" href="/">Back</a>
			<div className="hold"></div>
			<div className={current == "login" ? 'login' : 'none'}>
				<div className="title">Connect to</div>
				<div className="login-btns">
					<div className="btn1" onClick={connectEvmWallet}>
						{loading == 'login-evm' ? <div className="icons"><Spin /></div> :
							<div className="icons">
								<span className="icon1"></span>
								<span className="icon2"></span>
								<span className="icon3"></span>
								<span className="icon4"></span>
							</div>
						}
						<label>{loading == 'login-evm' ? connectStatus : 'EVM Wallet'}</label>
					</div>
					<div className="btn1" onClick={connectPolkdotWallet}>
						{loading == 'login-polkdot' ? <div className="icons"><Spin /></div> :
							<div className="icons">
								<span className="icon11"></span>
								<span className="icon12"></span>
							</div>
						}
						<label>{loading == 'login-polkdot' ? connectStatus : 'Polkadot Wallet'}</label>
					</div>
				</div>
			</div>
			<div className={current == "dashboard" ? 'dashboard' : 'none'}>
				<div className="b1">
					<div className="btn" onClick={onLogout}></div>
					<div className="line l1">{balance} CESS</div>
					<div className="line l2">Balance</div>
					<div className="line l3">
						<span className="txt" onClick={() => onCopy(showAddressType != 'CESS' ? accout.address : accout.evmAddresss)}>{formatter.formatAddressLong(showAddressType != 'CESS' ? accout.address : accout.evmAddress)}</span>
						<label className="icon" onClick={() => onCopy(showAddressType != 'CESS' ? accout.address : accout.evmAddress)}></label>
					</div>
					<div className={accountType != 'polkdot' ? "line l4" : "none"}>
						<label className="icon"></label>
						<span className="txt" onClick={() => setShowAddressType(showAddressType == 'CESS' ? 'EVM' : 'CESS')}>Show the {showAddressType} address</span>
					</div>
				</div>
				<div className="b2">
					<div className="btn-box btn1" onClick={() => onClick('Send')}>Send</div>
					<div className="btn-box btn2" onClick={() => onClick('Receive')}>Receive</div>
					<div className="btn-box btn3" onClick={() => onClick('Staking')}>Staking</div>
					<div className="btn-box btn4" onClick={() => onClick('Nominate')}>Nominate</div>
				</div>
				<div className="b3">
					<div className="b3-t">Asset Analysis</div>
					<div className="tb">
						<div className="tr">
							<span>Available</span>
							<label>{available} CESS</label>
						</div>
						<div className="tr">
							<span>Staking</span>
							<label>{staking} CESS</label>
						</div>
						<div className="tr">
							<span>Nominate</span>
							<label>{nominate} CESS</label>
						</div>
					</div>
				</div>
				<div className="b4">
					<div className="t1">History</div>
					<div className="tb">
						{
							historys && historys.map(t => {
								return (
									<div className="tr" key={t.key}>
										<div className="left">
											<span>{t.amount}</span>
											<label>{t.type}</label>
										</div>
										<div className="right">
											<span>From {t.from}</span>
											<label>To {t.to}</label>
											<font>{t.time}</font>
										</div>
									</div>
								)
							})
						}
						{
							!historys || historys.length == 0 ? (
								<div className="no-data">No data</div>
							) : ("")
						}
					</div>
					<div className={historys && historys.length && historyTotalPage > 1 ? "pager" : "none"}>
						<div className={pageIndex == 1 ? "none" : "pre"} onClick={() => onNextHistoryPage(-1)}></div>
						<div className={pageIndex >= historyTotalPage ? "none" : "next"} onClick={() => onNextHistoryPage(1)}></div>
					</div>
				</div>
			</div>
			<div className={"Send,Receive,Staking,Nominate".includes(current) ? 'box-out' : 'none'}>
				<div className="box">
					<div className="top-header">
						<div className="back" onClick={() => { setCurrent('dashboard'); loadHistoryList() }}></div>
						{boxTitle}
					</div>
					<div className={current == "Send" ? 'send' : 'none'}>
						<div className="myinput">
							<div className="tips">Amount</div>
							<textarea onChange={(e) => onInput(e, 'send', 'amount')} onInput={(e) => onInput(e, 'send', 'amount')} onKeyPress={(e) => onInput(e, 'send', 'amount')} placeholder="0" className="textarea1"></textarea>
						</div>
						<div className="t1">Balance: {available} CESS</div>
						<div className="myinput">
							<div className="tips">Receiving Address</div>
							<textarea onChange={(e) => onInput(e, 'send', 'address')} onInput={(e) => onInput(e, 'send', 'address')} onKeyPress={(e) => onInput(e, 'send', 'address')} placeholder="cX" className="textarea2"></textarea>
						</div>
						{
							loading == 'signature' ?
								(<div className="btn btn-disabled"><Spin size="small" />&nbsp;&nbsp;Loading...</div>) :
								(<div className="btn" onClick={onSend}>Signature</div>)
						}
					</div>
					<div className={current == "Receive" ? 'receive' : 'none'}>
						<div className="qr">{accout?.address && <QrSvg value={accout?.address} />}</div>
						<div className="show-address">
							<div className="tips">Receiving Address</div>
							<div className="address">{accout?.address}</div>
							<div className="btn-copy" onClick={() => onCopy(accout?.address)}></div>
						</div>
					</div>
					<div className={current == "Staking" ? 'staking' : 'none'}>
						<div className="myinput">
							<div className="tips">Staking Amount(CESS)</div>
							<textarea onChange={(e) => onInput(e, 'staking', 'amount')} onInput={(e) => onInput(e, 'staking', 'amount')} onKeyPress={(e) => onInput(e, 'staking', 'amount')} placeholder="0" className="textarea1"></textarea>
						</div>
						<div className="t1">Balance: {available} CESS</div>
						<div className="myinput">
							<div className="tips">Storage Miner Account</div>
							<textarea onChange={(e) => onInput(e, 'staking', 'address')} onInput={(e) => onInput(e, 'staking', 'address')} onKeyPress={(e) => onInput(e, 'staking', 'address')} placeholder="cX" className="textarea2"></textarea>
						</div>
						{
							loading == 'signature' ?
								(<div className="btn btn-disabled"><Spin size="small" />&nbsp;&nbsp;Loading...</div>) :
								(<div className="btn" onClick={onStaking}>Signature</div>)
						}
					</div>
					<div className={current == "Nominate" ? 'nominate' : 'none'}>
						<div className="myinput">
							<div className="tips">Staking Amount</div>
							<textarea onChange={(e) => onInput(e, 'nominate', 'amount')} onInput={(e) => onInput(e, 'nominate', 'amount')} onKeyPress={(e) => onInput(e, 'nominate', 'amount')} placeholder="0" className="textarea1"></textarea>
						</div>
						<div className="t1">Balance: {available} CESS</div>
						<div className="myinput">
							<div className="tips">Consensus Account</div>
							<textarea onChange={(e) => onInput(e, 'nominate', 'address')} onInput={(e) => onInput(e, 'nominate', 'address')} onKeyPress={(e) => onInput(e, 'nominate', 'address')} placeholder="cX" className="textarea2"></textarea>
						</div>
						{
							loading == 'signature' ?
								(<div className="btn btn-disabled"><Spin size="small" />&nbsp;&nbsp;Loading...</div>) :
								(<div className="btn" onClick={onNominate}>Signature</div>)
						}
					</div>
				</div>
			</div>
		</div>
	);
}
